home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC] / NeXTSTEP 3.3 Dev Intel.iso / NextDeveloper / Source / GNU / cc / bc-emit.c < prev    next >
C/C++ Source or Header  |  1993-10-12  |  21KB  |  988 lines

  1. /* Output bytecodes for GNU C-compiler.
  2.    Copyright (C) 1993 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU CC.
  5.  
  6. GNU CC is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU CC is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU CC; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. #include "config.h"
  22. #include "gvarargs.h"
  23. #include "machmode.h"
  24. #include "rtl.h"
  25. #include "real.h"
  26. #include "obstack.h"
  27. #include "bytecode.h"
  28. #ifdef __GNUC__
  29. #include "bytetypes.h"
  30. #endif
  31. #include "bc-emit.h"
  32. #include "bc-opcode.h"
  33. #include "bc-typecd.h"
  34. #include "bi-run.h"
  35.  
  36. #include <stdio.h>
  37.  
  38. extern char *xmalloc (), *xrealloc ();
  39. extern void free ();
  40.  
  41. extern struct obstack *rtl_obstack;
  42.  
  43. /* Indexed by mode class, gives the narrowest mode for each class.  */
  44.  
  45. enum machine_mode class_narrowest_mode[(int) MAX_MODE_CLASS];
  46.  
  47. /* Commonly used modes.  */
  48. /* Mode whose width is BITS_PER_UNIT */
  49. enum machine_mode byte_mode;
  50.  
  51. /* Mode whose width is BITS_PER_WORD */
  52. enum machine_mode word_mode;
  53.  
  54. /* Vector indexed by opcode giving info about the args for each opcode. */
  55. static struct arityvec arityvec[] = {
  56. #include "bc-arity.h"
  57. };
  58.  
  59. /* How to print a symbol name for the assembler.  */
  60. static void
  61. prsym (file, s)
  62.      FILE *file;
  63.      char *s;
  64. {
  65.   if (*s == '*')
  66.     fprintf (file, "%s", s + 1);
  67.   else
  68.  
  69. #ifdef NAMES_HAVE_UNDERSCORES
  70.     fprintf (file, "_%s", s);
  71. #else
  72.     fprintf (file, "%s", s);
  73. #endif
  74.  
  75. }
  76.  
  77. /* Maintain a bucket hash table for symbol names. */
  78.  
  79. #define HASH_BITS 32
  80. #define HASH_SIZE 509
  81.  
  82. static struct bc_sym *hashtab[HASH_SIZE];
  83.  
  84. static unsigned int
  85. hash (name)
  86.      char *name;
  87. {
  88.   unsigned int hash = 0;
  89.  
  90.   while (*name)
  91.     {
  92.       hash = hash << 3 | hash >> HASH_BITS - 3;
  93.       hash += *name++;
  94.     }
  95.  
  96.   return hash % HASH_SIZE;
  97. }
  98.  
  99.  
  100. /* Look up the named symbol, creating it if it doesn't exist. */
  101. struct bc_sym *
  102. sym_lookup (name)
  103.      char *name;
  104. {
  105.   int i;
  106.   struct bc_sym *s;
  107.  
  108.   i = hash (name);
  109.   for (s = hashtab[i]; s; s = s->next)
  110.     if (!strcmp (s->name, name))
  111.       return s;
  112.  
  113.   s = (struct bc_sym *) xmalloc (sizeof (struct bc_sym));
  114.   s->name = xmalloc (strlen (name) + 1);
  115.   strcpy (s->name, name);
  116.   s->defined = s->global = s->common = 0;
  117.   s->val = 0;
  118.   s->next = hashtab[i];
  119.   hashtab[i] = s;
  120.   return s;
  121. }
  122.  
  123.  
  124. /* Write out .globl and common symbols to the named file.  */
  125. static void
  126. bc_sym_write (file)
  127.      FILE *file;
  128. {
  129.   int i;
  130.   struct bc_sym *s;
  131.  
  132.   for (i = 0; i < HASH_SIZE; ++i)
  133.     for (s = hashtab[i]; s; s = s->next)
  134.       {
  135.     if (s->global)
  136.       {
  137.         fprintf (file, "\n\t.globl ");
  138.         prsym (file, s->name);
  139.         putc ('\n', file);
  140.         if (s->common)
  141.           {
  142.         fprintf (file, "\n\t.comm ");
  143.         prsym (file, s->name);
  144.         fprintf (file, ", %d\n", s->val);
  145.           }
  146.       }
  147.     else if (s->common)
  148.       {
  149.         fprintf (file, "\n\t.lcomm ");
  150.         prsym (file, s->name);
  151.         fprintf (file, ", %d\n", s->val);
  152.       }
  153.       }
  154. }
  155.  
  156.  
  157.  
  158.  
  159. /* Create and initialize a new segment. */
  160. static struct bc_seg *
  161. seg_create ()
  162. {
  163.   struct bc_seg *result;
  164.  
  165.   result = (struct bc_seg *) xmalloc (sizeof (struct bc_seg));
  166.   result->alloc = 256;
  167.   result->data = xmalloc (result->alloc);
  168.   result->size = 0;
  169.   result->syms = 0;
  170.   result->relocs = 0;
  171.   return result;
  172. }
  173.  
  174.  
  175. /* Advance the segment index to the next alignment boundary. */
  176. static void
  177. seg_align (seg, log)
  178.      struct bc_seg *seg;
  179.      int log;
  180. {
  181.   unsigned int oldsize = seg->size;
  182.  
  183.   seg->size = seg->size + (1 << log) - 1 & ~((1 << log) - 1);
  184.   if (seg->size > seg->alloc)
  185.     {
  186.       while (seg->size > seg->alloc)
  187.     seg->alloc *= 2;
  188.       seg->data = xrealloc (seg->data, seg->alloc);
  189.     }
  190.   bzero (seg->data + oldsize, seg->size - oldsize);
  191. }
  192.  
  193.  
  194. /* Append the given data to the given segment. */
  195. static void
  196. seg_data (seg, data, size)
  197.      struct bc_seg *seg;
  198.      char *data;
  199.      unsigned int size;
  200. {
  201.   if (seg->size + size > seg->alloc)
  202.     {
  203.       while (seg->size + size > seg->alloc)
  204.     seg->alloc *= 2;
  205.       seg->data = xrealloc (seg->data, seg->alloc);
  206.     }
  207.  
  208.   bcopy (data, seg->data + seg->size, size);
  209.   seg->size += size;
  210. }
  211.  
  212.  
  213. /* Append a zero-filled skip to the given segment.  */
  214. static void
  215. seg_skip (seg, size)
  216.      struct bc_seg *seg;
  217.      unsigned int size;
  218. {
  219.   if (seg->size + size > seg->alloc)
  220.     {
  221.       while (seg->size + size > seg->alloc)
  222.     seg->alloc *= 2;
  223.       seg->data = xrealloc (seg->data, seg->alloc);
  224.     }
  225.  
  226.   memset (seg->data + seg->size, 0, size);
  227.   seg->size += size;
  228. }
  229.  
  230.  
  231. /* Define the given name as the current offset in the given segment.  It
  232.    is an error if the name is already defined.  Return 0 or 1 indicating
  233.    failure or success respectively. */
  234. static int
  235. seg_defsym (seg, name)
  236.      struct bc_seg *seg;
  237.      char *name;
  238. {
  239.   struct bc_sym *sym;
  240.   struct bc_segsym *segsym;
  241.  
  242.   sym = sym_lookup (name);
  243.   if (sym->defined)
  244.     return 0;
  245.  
  246.   sym->defined = 1;
  247.   sym->val = seg->size;
  248.   segsym = (struct bc_segsym *) xmalloc (sizeof (struct bc_segsym));
  249.   segsym->sym = sym;
  250.   segsym->next = seg->syms;
  251.   seg->syms = segsym;
  252.   return 1;
  253. }
  254.  
  255.  
  256. /* Generate in seg's data a reference to the given sym, adjusted by
  257.    the given offset. */
  258. static void
  259. seg_refsym (seg, name, offset)
  260.      struct bc_seg *seg;
  261.      char *name;
  262.      int offset;
  263. {
  264.   struct bc_sym *sym;
  265.   struct bc_segreloc *segreloc;
  266.  
  267.   sym = sym_lookup (name);
  268.   segreloc = (struct bc_segreloc *) xmalloc (sizeof (struct bc_segreloc));
  269.   segreloc->offset = seg->size;
  270.   segreloc->sym = sym;
  271.   segreloc->next = seg->relocs;
  272.   seg->relocs = segreloc;
  273.   seg_data (seg, (char *) &offset, sizeof offset);
  274. }
  275.  
  276.  
  277. /* Concatenate the contents of given segments into the first argument. */
  278. static void
  279. seg_concat (result, seg)
  280.      struct bc_seg *result, *seg;
  281. {
  282.   unsigned int fix;
  283.   struct bc_segsym *segsym;
  284.   struct bc_segreloc *segreloc;
  285.  
  286.   seg_align (result, MACHINE_SEG_ALIGN);
  287.   fix = result->size;
  288.   seg_data (result, seg->data, seg->size);
  289.   free (seg->data);
  290.  
  291.   /* Go through the symbols and relocs of SEG, adjusting their offsets
  292.      for their new location in RESULT. */
  293.   if (seg->syms)
  294.     {
  295.       segsym = seg->syms;
  296.       do
  297.     segsym->sym->val += fix;
  298.       while (segsym->next && (segsym = segsym->next));
  299.       segsym->next = result->syms;
  300.       result->syms = seg->syms;
  301.     }
  302.   if (seg->relocs)
  303.     {
  304.       segreloc = seg->relocs;
  305.       do
  306.     segreloc->offset += fix;
  307.       while (segreloc->next && (segreloc = segreloc->next));
  308.       segreloc->next = result->relocs;
  309.       result->relocs = seg->relocs;
  310.     }
  311.  
  312.   free ((char *) seg);
  313. }
  314.  
  315. /* Write a segment to a file.  */
  316. static void
  317. bc_seg_write (seg, file)
  318.      struct bc_seg *seg;
  319.      FILE *file;
  320. {
  321.   struct bc_segsym *segsym, *nsegsym, *psegsym;
  322.   struct bc_segreloc *segreloc, *nsegreloc, *psegreloc;
  323.   int i, offset, flag;
  324.  
  325.   /* Reverse the list of symbols.  */
  326.   for (psegsym = 0, segsym = seg->syms; segsym; segsym = nsegsym)
  327.     {
  328.       nsegsym = segsym->next;
  329.       segsym->next = psegsym;
  330.       psegsym = segsym;
  331.     }
  332.   seg->syms = psegsym;
  333.  
  334.   /* Reverse the list of relocs.  */
  335.   for (psegreloc = 0, segreloc = seg->relocs; segreloc; segreloc = nsegreloc)
  336.     {
  337.       nsegreloc = segreloc->next;
  338.       segreloc->next = psegreloc;
  339.       psegreloc = segreloc;
  340.     }
  341.   seg->relocs = psegreloc;
  342.  
  343.   /* Output each byte of the segment.  */
  344.   for (i = 0, segsym = seg->syms, segreloc = seg->relocs; i < seg->size; ++i)
  345.     {
  346.       while (segsym && segsym->sym->val == i)
  347.     {
  348.       if (i % 8 != 0)
  349.         putc ('\n', file);
  350.  
  351.       BC_WRITE_SEGSYM (segsym, file);
  352.       segsym = segsym->next;
  353.       flag = 1;
  354.     }
  355.       if (segreloc && segreloc->offset == i)
  356.     {
  357.       if (i % 8 != 0)
  358.         putc ('\n', file);
  359.  
  360.       offset = *(int *) (seg->data + i);
  361.       i += sizeof (int) - 1;
  362.  
  363.       BC_WRITE_RELOC_ENTRY (segreloc, file, offset);
  364.       segreloc = segreloc->next;
  365.       flag = 1;
  366.     }
  367.       else
  368.     {
  369.       if (i % 8 == 0 || flag)
  370.         BC_START_BYTECODE_LINE (file);
  371.  
  372.       BC_WRITE_BYTECODE (i % 8 == 0 || flag ? ' ' : ',',
  373.                  seg->data[i] & 0xFF,
  374.                  file);
  375.       flag = 0;
  376.       if (i % 8 == 7)
  377.         putc ('\n', file);
  378.     }
  379.     }
  380.  
  381.   /* Paranoia check--we should have visited all syms and relocs during
  382.      the output pass.  */
  383.  
  384.   if (segsym || segreloc)
  385.     abort ();
  386. }
  387.  
  388.  
  389.  
  390. /* Text and data segments of the object file in making. */
  391. static struct bc_seg *bc_text_seg;
  392. static struct bc_seg *bc_data_seg;
  393.  
  394. /* Called before anything else in this module. */
  395. void
  396. bc_initialize ()
  397. {
  398.   int min_class_size[(int) MAX_MODE_CLASS];
  399.   enum machine_mode mode;
  400.   int i;
  401.  
  402.   bc_init_mode_to_code_map ();
  403.  
  404.   bc_text_seg = seg_create ();
  405.   bc_data_seg = seg_create ();
  406.  
  407.   dconst0 = REAL_VALUE_ATOF ("0", DFmode);
  408.   dconst1 = REAL_VALUE_ATOF ("1", DFmode);
  409.   dconst2 = REAL_VALUE_ATOF ("2", DFmode);
  410.   dconstm1 = REAL_VALUE_ATOF ("-1", DFmode);
  411.  
  412.   /* Find the narrowest mode for each class and compute the word and byte
  413.      modes.  */
  414.  
  415.   for (i = 0; i < (int) MAX_MODE_CLASS; i++)
  416.     min_class_size[i] = 1000;
  417.  
  418.   for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
  419.        mode = (enum machine_mode) ((int) mode + 1))
  420.     {
  421.       if (GET_MODE_SIZE (mode) < min_class_size[(int) GET_MODE_CLASS (mode)])
  422.     {
  423.       class_narrowest_mode[(int) GET_MODE_CLASS (mode)] = mode;
  424.       min_class_size[(int) GET_MODE_CLASS (mode)] = GET_MODE_SIZE (mode);
  425.     }
  426.       if (GET_MODE_CLASS (mode) == MODE_INT
  427.       && GET_MODE_BITSIZE (mode) == BITS_PER_UNIT)
  428.     byte_mode = mode;
  429.  
  430.       if (GET_MODE_CLASS (mode) == MODE_INT
  431.       && GET_MODE_BITSIZE (mode) == BITS_PER_WORD)
  432.     word_mode = mode;
  433.     }
  434. }
  435.  
  436.  
  437. /* External addresses referenced in a function.  Rather than trying to
  438.    work relocatable address directly into bytecoded functions (which would
  439.    require us to provide hairy location info and possibly obey alignment
  440.    rules imposed by the architecture) we build an auxilary table of
  441.    pointer constants, and encode just offsets into this table into the
  442.    actual bytecode. */
  443. static struct bc_seg *ptrconsts;
  444.  
  445. /* Trampoline code for the function entry.  */
  446. struct bc_seg *trampoline;
  447.  
  448. /* Actual byte code of the function. */
  449. struct bc_seg *bytecode;
  450.  
  451. /* List of labels defined in the function. */
  452. struct bc_label *labels;
  453.  
  454. /* List of label references in the function. */
  455. struct bc_labelref *labelrefs;
  456.  
  457.  
  458. /* Add symbol to pointer table.  Return offset into table where
  459.    pointer was stored.  The offset usually goes into the bytecode
  460.    stream as a constP literal. */
  461. int
  462. bc_define_pointer (p)
  463.      char *p;
  464. {
  465.   int offset = ptrconsts->size;
  466.  
  467.   seg_refsym (ptrconsts, p, 0);
  468.   return offset;
  469. }
  470.  
  471.  
  472. /* Begin a bytecoded function.  */
  473. int
  474. bc_begin_function (name)
  475.     char *name;
  476. {
  477.   ptrconsts = seg_create ();
  478.   trampoline = seg_create ();
  479.   bytecode = seg_create ();
  480.   return seg_defsym (trampoline, name);
  481. }
  482.  
  483.  
  484. /* Force alignment in inline bytecode.  */
  485. void
  486. bc_align_bytecode (align)
  487.     int align;
  488. {
  489.   seg_align (bytecode, align);
  490. }
  491.  
  492.  
  493. /* Emit data inline into bytecode.  */
  494. void
  495. bc_emit_bytecode_const (data, size)
  496.      char *data;
  497.      unsigned int size;
  498. {
  499.   if (bytecode)
  500.     seg_data (bytecode, data, size);
  501. }
  502.  
  503.  
  504. /* Create a new "bytecode label", to have its value defined later.
  505.    Bytecode labels have nothing to do with the object file symbol table,
  506.    and are purely local to a given bytecoded function. */
  507. struct bc_label *
  508. bc_get_bytecode_label ()
  509. {
  510.   struct bc_label *result;
  511.  
  512.   result = (struct bc_label *) xmalloc (sizeof (struct bc_label));
  513.   result->defined = 0;
  514.   result->next = labels;
  515.   result->uid = 0;
  516.   labels = result;
  517.   return result;
  518. }
  519.  
  520.  
  521. /* Define the given label with the current location counter. */
  522. int
  523. bc_emit_bytecode_labeldef (label)
  524.      struct bc_label *label;
  525. {
  526.   extern int bc_new_uid ();
  527.  
  528.   if (!label || label->defined)
  529.     return 0;
  530.  
  531.   label->offset = bytecode->size;
  532.   label->defined = 1;
  533.   label->uid = bc_new_uid ();
  534.  
  535. #ifdef DEBUG_PRINT_CODE
  536.   fprintf (stderr, "$%lx:\n", label);
  537. #endif
  538.  
  539.   return 1;
  540. }
  541.  
  542.  
  543. /* Generate a location-relative reference to the given bytecode label.
  544.    It need not be defined yet; label references will be backpatched later. */
  545. void
  546. bc_emit_bytecode_labelref (label)
  547.      struct bc_label *label;
  548. {
  549.   struct bc_labelref *labelref;
  550.   static int zero;
  551.  
  552.   labelref = (struct bc_labelref *) xmalloc (sizeof (struct bc_labelref));
  553.   labelref->label = label;
  554.   labelref->offset = bytecode->size;
  555.   labelref->next = labelrefs;
  556.   labelrefs = labelref;
  557.  
  558. #ifdef DEBUG_PRINT_CODE
  559.   fprintf (stderr, " $%lx", label);
  560. #endif
  561.  
  562.   seg_data (bytecode, (char *) &zero, sizeof zero);
  563. }
  564.  
  565.  
  566. /* Emit a reference to an external address; generate the reference in the
  567.    ptrconst area, and emit an offset in the bytecode. */
  568. void
  569. bc_emit_code_labelref (name, offset)
  570.      char *name;
  571.      int offset;
  572. {
  573.   int ptroff;
  574.  
  575.   ptroff = ptrconsts->size / sizeof (char *);
  576.   seg_data (bytecode, (char *) &ptroff, sizeof ptroff);
  577.   seg_refsym (ptrconsts, name, offset);
  578.  
  579. #ifdef DEBUG_PRINT_CODE
  580.   fprintf (stderr, " [external <%x> %s]", ptroff, name);
  581. #endif
  582. }
  583.  
  584.  
  585. /* Backpatch label references in the byte code, and concatenate the bytecode
  586.    and pointer constant segments to the cumulative text for the object file.
  587.    Return a label name for the pointer constants region.  */
  588. char *
  589. bc_end_function ()
  590. {
  591.   int addr;
  592.   struct bc_label *label, *next;
  593.   struct bc_labelref *ref, *nextref;
  594.   char ptrconsts_label[20];
  595.   static int nlab;
  596.  
  597.   /* Backpatch bytecode label references. */
  598.   for (ref = labelrefs; ref; ref = ref->next)
  599.     if (ref->label->defined)
  600.       {
  601.     addr = ref->label->offset;
  602.     bcopy (&addr, bytecode->data + ref->offset, sizeof addr);
  603.       }
  604.  
  605.   /* Free the chains of labelrefs and labeldefs. */
  606.   for (ref = labelrefs; ref; ref = nextref)
  607.     {
  608.       nextref = ref->next;
  609.       free ((char *) ref);
  610.     }
  611.  
  612.   for (label = labels; label; label = next)
  613.     {
  614.       next = label->next;
  615.       free ((char *) label);
  616.     }
  617.  
  618.   seg_concat (trampoline, bytecode);
  619.   seg_align (trampoline, MACHINE_SEG_ALIGN);
  620.   sprintf (ptrconsts_label, "*LP%d", nlab++);
  621.   seg_defsym (trampoline, ptrconsts_label);
  622.   seg_concat (trampoline, ptrconsts);
  623.   seg_concat (bc_text_seg, trampoline);
  624.  
  625.   labels = 0;
  626.   labelrefs = 0;
  627.   trampoline = 0;
  628.   bytecode = 0;
  629.   ptrconsts = 0;
  630.  
  631.   return sym_lookup (ptrconsts_label)->name;
  632. }
  633.  
  634. /* Force alignment in const data. */
  635. void
  636. bc_align_const (align)
  637.      int align;
  638. {
  639.   seg_align (bc_text_seg, align);
  640. }
  641.  
  642. /* Emit const data. */
  643. void
  644. bc_emit_const (data, size)
  645.      char *data;
  646.      unsigned int size;
  647. {
  648.   seg_data (bc_text_seg, data, size);
  649. }
  650.  
  651. /* Emit a zero-filled constant skip. */
  652. void
  653. bc_emit_const_skip (size)
  654.      unsigned int size;
  655. {
  656.   seg_skip (bc_text_seg, size);
  657. }
  658.  
  659. /* Emit a label definition in const data. */
  660. int
  661. bc_emit_const_labeldef (name)
  662.      char *name;
  663. {
  664.   return seg_defsym (bc_text_seg, name);
  665. }
  666.  
  667. /* Emit a label reference in const data. */
  668. void
  669. bc_emit_const_labelref (name, offset)
  670.      char *name;
  671.      int offset;
  672. {
  673.   seg_refsym (bc_text_seg, name, offset);
  674. }
  675.  
  676. /* Force alignment in data. */
  677. void
  678. bc_align_data (align)
  679.      int align;
  680. {
  681.   seg_align (bc_data_seg, align);
  682. }
  683.  
  684. /* Emit data. */
  685. void
  686. bc_emit_data (data, size)
  687.      char *data;
  688.      unsigned int size;
  689. {
  690.   seg_data (bc_data_seg, data, size);
  691. }
  692.  
  693. /* Emit a zero-filled data skip.  */
  694. void
  695. bc_emit_data_skip (size)
  696.      unsigned int size;
  697. {
  698.   seg_skip (bc_data_seg, size);
  699. }
  700.  
  701. /* Emit label definition in data. */
  702. int
  703. bc_emit_data_labeldef (name)
  704.      char *name;
  705. {
  706.   return seg_defsym (bc_data_seg, name);
  707. }
  708.  
  709. /* Emit label reference in data. */
  710. void
  711. bc_emit_data_labelref (name, offset)
  712.      char *name;
  713.      int offset;
  714. {
  715.   seg_refsym (bc_data_seg, name, offset);
  716. }
  717.  
  718. /* Emit a common block of the given name and size.  Note that
  719.    when the .o file is actually written non-global "common"
  720.    blocks will have to be turned into space in the data section.  */
  721. int
  722. bc_emit_common (name, size)
  723.      char *name;
  724.      unsigned int size;
  725. {
  726.   struct bc_sym *sym;
  727.  
  728.   sym = sym_lookup (name);
  729.   if (sym->defined)
  730.     return 0;
  731.  
  732.   sym->defined = 1;
  733.   sym->common = 1;
  734.   sym->val = size;
  735.   return 1;
  736. }
  737.  
  738. /* Globalize the given label. */
  739. void
  740. bc_globalize_label (name)
  741.      char *name;
  742. {
  743.   struct bc_sym *sym;
  744.  
  745.   sym = sym_lookup (name);
  746.   sym->global = 1;
  747. }
  748.  
  749. static enum { in_text, in_data } section = in_text;
  750.  
  751. void
  752. bc_text ()
  753. {
  754.   section = in_text;
  755. }
  756.  
  757. void
  758. bc_data ()
  759. {
  760.   section = in_data;
  761. }
  762.  
  763. void
  764. bc_align (align)
  765.      int align;
  766. {
  767.   if (section == in_text)
  768.     bc_align_const (align);
  769.   else
  770.     bc_align_data (align);
  771. }
  772.  
  773. void
  774. bc_emit (data, size)
  775.      char *data;
  776.      unsigned int size;
  777. {
  778.   if (section == in_text)
  779.     bc_emit_const (data, size);
  780.   else
  781.     bc_emit_data (data, size);
  782. }
  783.  
  784. void
  785. bc_emit_skip (size)
  786.      unsigned int size;
  787. {
  788.   if (section == in_text)
  789.     bc_emit_const_skip (size);
  790.   else
  791.     bc_emit_data_skip (size);
  792. }
  793.  
  794. int
  795. bc_emit_labeldef (name)
  796.      char *name;
  797. {
  798.   if (section == in_text)
  799.     return bc_emit_const_labeldef (name);
  800.   else
  801.     return bc_emit_data_labeldef (name);
  802. }
  803.  
  804. void
  805. bc_emit_labelref (name, offset)
  806.      char *name;
  807.      int offset;
  808. {
  809.   if (section == in_text)
  810.     bc_emit_const_labelref (name, offset);
  811.   else
  812.     bc_emit_data_labelref (name, offset);
  813. }
  814.  
  815. void
  816. bc_write_file (file)
  817.      FILE *file;
  818. {
  819.   BC_WRITE_FILE (file);
  820. }
  821.  
  822.  
  823. /* Allocate a new bytecode rtx.
  824.    If you supply a null BC_LABEL, we generate one.  */
  825.  
  826. rtx
  827. bc_gen_rtx (label, offset, bc_label)
  828.      char *label;
  829.      int offset;
  830.      struct bc_label *bc_label;
  831. {
  832.   rtx r;
  833.  
  834.   if (bc_label == 0)
  835.     bc_label = (struct bc_label *) xmalloc (sizeof (struct bc_label));
  836.  
  837.   r = gen_rtx (CODE_LABEL, VOIDmode, label, bc_label);
  838.   bc_label->offset = offset;
  839.  
  840.   return r;
  841. }
  842.  
  843.  
  844. /* Print bytecode rtx */
  845. void
  846. bc_print_rtl (fp, r)
  847.      FILE *fp;
  848.      rtx r;
  849. {
  850. #if 0 /* This needs to get fixed to really work again.  */
  851.   /* BC_WRITE_RTL has a definition
  852.      that doesn't even make sense for this use.  */
  853.   BC_WRITE_RTL (r, fp);
  854. #endif
  855. }
  856.  
  857.  
  858. /* Emit a bytecode, keeping a running tally of the stack depth.  */
  859. void
  860. bc_emit_bytecode (bytecode)
  861.      enum bytecode_opcode bytecode;
  862. {
  863.   char byte;
  864.   int npushes = arityvec[(int) bytecode].noutputs - arityvec[(int) bytecode].ninputs;
  865.   static int prev_lineno = -1;
  866.  
  867.   byte = bytecode;
  868.  
  869. #ifdef BCDEBUG_PRINT_CODE
  870.   if (lineno != prev_lineno)
  871.     {
  872.       fprintf (stderr, "<line %d>\n", lineno);
  873.       prev_lineno = lineno;
  874.     }
  875.  
  876.   fputs (opcode_name[(unsigned int) bytecode], stderr);
  877. #endif
  878.  
  879.   /* Due to errors we are often requested to output bytecodes that
  880.      will cause an interpreter stack undeflow when executed.  Instead of
  881.      dumping core on such occasions, we omit the bytecode.  Erroneous code
  882.      should not be executed, regardless.  This makes life much easier, since
  883.      we don't have to deceive ourselves about the known stack depth. */
  884.  
  885.   bc_emit_bytecode_const (&byte, 1);
  886.  
  887.   if ((stack_depth -= arityvec[(int) bytecode].ninputs) >= 0)
  888.     {
  889.       if ((stack_depth += arityvec[(int) bytecode].noutputs) > max_stack_depth)
  890.     max_stack_depth = stack_depth;
  891.     }
  892.  
  893. #ifdef VALIDATE_STACK_FOR_BC
  894.   VALIDATE_STACK_FOR_BC ();
  895. #endif
  896. }
  897.  
  898.  
  899. #ifdef BCDEBUG_PRINT_CODE
  900. #define PRLIT(TYPE, PTR)  fprintf (stderr, " [%x]", *(TYPE *) PTR)
  901. #else
  902. #define PRLIT(X,Y)
  903. #endif
  904.  
  905. /* Emit a complete bytecode instruction, expecting the correct number
  906.    of literal values in the call.  First argument is the instruction, the
  907.    remaining arguments are literals of size HOST_WIDE_INT or smaller. */
  908. void
  909. bc_emit_instruction (va_alist)
  910.      va_dcl
  911. {
  912.   va_list arguments;
  913.   enum bytecode_opcode opcode;
  914.   int nliteral, instruction;
  915.  
  916.  
  917.   va_start (arguments);
  918.  
  919.   /* Emit instruction bytecode */
  920.   opcode = va_arg (arguments, enum bytecode_opcode);
  921.   bc_emit_bytecode (opcode);
  922.   instruction = (int) opcode;
  923.  
  924.   /* Loop literals and emit as bytecode constants */
  925.   for (nliteral = 0; nliteral < arityvec[instruction].nliterals; nliteral++)
  926.     {
  927.       HOST_WIDE_INT literal;
  928.  
  929.       switch (arityvec[instruction].literals[nliteral])
  930.     {
  931. /* This conditional is a kludge, but it's necessary
  932.    because TYPE might be long long.  */
  933. #ifdef __GNUC__
  934.       /* Expand definitions into case statements */
  935. #define DEFTYPECODE(CODE, NAME, MODE, TYPE)                \
  936.     case CODE:                            \
  937.       {                                \
  938.         TYPE temp = va_arg (arguments, TYPE);             \
  939.         bc_emit_bytecode_const ((void *) &temp, sizeof temp);     \
  940.         PRLIT (TYPE, &temp); }                    \
  941.       break;
  942.  
  943. #include "bc-typecd.def"
  944.  
  945. #undef DEFTYPECODE
  946. #endif /* __GNUC__ */
  947.  
  948.     default:
  949.       abort ();
  950.     }
  951.     }
  952.  
  953. #ifdef BCDEBUG_PRINT_CODE
  954.   fputc ('\n', stderr);
  955. #endif
  956. }
  957.  
  958. /* Emit the machine-code interface trampoline at the beginning of a byte
  959.    coded function.  The argument is a label name of the interpreter
  960.    bytecode callinfo structure; the return value is a label name for
  961.    the beginning of the actual bytecode.  */
  962. char *
  963. bc_emit_trampoline (callinfo)
  964.      char *callinfo;
  965. {
  966.   char mylab[20];
  967.   static int n;
  968.  
  969.   sprintf (mylab, "*LB%d", n++);
  970.   
  971.   BC_EMIT_TRAMPOLINE (trampoline, callinfo);
  972.  
  973.   seg_defsym (bytecode, mylab);
  974.   return sym_lookup (mylab)->name;
  975. }
  976.  
  977.  
  978. /* Simple strdup */
  979. char *
  980. bc_xstrdup (str)
  981.      char *str;
  982. {
  983.   char *tmp = xmalloc (strlen (str) + 1);
  984.  
  985.   strcpy (tmp, str);
  986.   return tmp;
  987. }
  988.